package com.aiwiown.snackmq.broker.handler;

import com.aiwiown.snackmq.cluster.metadata.MetadataManager;
import com.aiwiown.snackmq.cluster.metadata.TopicMetadata;
import com.aiwiown.snackmq.common.dto.TopicInfo;
import com.aiwiown.snackmq.common.handler.MessageHandler;
import com.aiwiown.snackmq.common.handler.RequestContext;
import com.aiwiown.snackmq.common.message.Message;
import com.aiwiown.snackmq.common.message.MessageStatus;
import com.aiwiown.snackmq.common.message.MessageType;
import com.aiwiown.snackmq.common.serialization.JsonSerializer;
import com.aiwiown.snackmq.common.serialization.SerializerFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.stream.Collectors;

/**
 * FetchTopicMetadataHandler 处理获取主题元数据的请求。
 * 它通过 MetadataManager 获取主题的元数据，并将其作为响应返回给客户端。
 */
@Slf4j
@RequiredArgsConstructor
public class FetchTopicMetadataHandler implements MessageHandler {

    // MetadataManager 用于管理主题的元数据
    private final MetadataManager metadataManager;
    // JsonSerializer 用于序列化和反序列化 JSON 数据
    private final JsonSerializer serializer = SerializerFactory.getJsonSerializer();

    /**
     * 实现接口要求的方法，告诉 MessageDispatcher 此 Handler 的职责。
     */
    @Override
    public MessageType getMessageType() {
        return MessageType.FETCH_TOPIC_METADATA;
    }

    /**
     * 处理获取主题元数据的请求。
     *
     * @param ctx 请求上下文，用于写入响应
     * @param message 客户端发送的请求消息
     */
    @Override
    public void handle(RequestContext ctx, Message message) {
        // 获取消息中的主题名称
        String topicName = message.getTopic();
        // 检查主题名称是否为空
        if (topicName == null || topicName.isEmpty()) {
            // 如果主题名称为空，返回错误响应
            ctx.writeResponse(Message.builder()
                    .messageId(message.getMessageId())
                    .type(MessageType.RESPONSE)
                    .status(MessageStatus.FAILED)
                    .errorMessage("Topic name is required for fetching metadata.")
                    .build());
            return;
        }

        // 从 MetadataManager 获取主题的元数据
        TopicMetadata topicMetadata = metadataManager.getTopic(topicName);
        // 检查主题元数据是否存在
        if (topicMetadata == null) {
            // 如果主题元数据不存在，返回未找到的响应
            ctx.writeResponse(Message.builder()
                    .messageId(message.getMessageId())
                    .type(MessageType.RESPONSE)
                    .status(MessageStatus.NOT_FOUND)
                    .errorMessage("Topic not found: " + topicName)
                    .build());
            return;
        }

        // ======================= 【核心调整：丰富元数据】 =======================
        // 【核心修复】根据 TopicInfo DTO 的新结构构建响应。
        // 它现在需要分区数、副本因子以及一个包含 Leader 和 Replicas 的映射。
        Map<Integer, TopicInfo.PartitionAssignmentInfo> assignments = topicMetadata.getPartitionAssignments().entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> {
                            // 【修复】直接传递 BrokerId 对象和 List<BrokerId>，而不是字符串
                            TopicMetadata.PartitionAssignment pa = entry.getValue();
                            return new TopicInfo.PartitionAssignmentInfo(pa.getLeader(), pa.getReplicas());
                        }
                ));

        // 【修复】使用正确的 TopicInfo 构造函数参数顺序
        TopicInfo topicInfo = new TopicInfo(topicMetadata.getPartitionCount(), topicMetadata.getReplicationFactor(), topicMetadata.getTopicName(), assignments);

        // 序列化并发送包含更丰富信息的响应
        byte[] body = serializer.serialize(topicInfo);
        Message response = Message.builder()
                .messageId(message.getMessageId())
                .type(MessageType.RESPONSE)
                .status(MessageStatus.SUCCESS)
                .body(body)
                .build();

        ctx.writeResponse(response);
    }
}
